import serial
import time
import struct
import numpy as np
from threading import Thread
from preprocess import remove_bcg_distortion, extract_heart_signal

fs = 100  # Hz
buff_time = fs * 60
signal_buff = np.zeros((buff_time,))


def get_data():
    # 使用全局变量signal_buff
    global signal_buff
    user_serial = serial.Serial('/dev/ttyS1', baudrate=115200, timeout=100)
    data_serial = serial.Serial('/dev/ttyS2', baudrate=512000, timeout=100)
    profile = open('profile_3_0_0.cfg',
                   mode='r', encoding='utf-8')

    # 写芯片启动命令
    while True:
        cmdline = profile.readline()
        if cmdline:
            time.sleep(1)
            print(cmdline)
            temp = bytes(cmdline, encoding='ASCII')
            user_serial.write(temp)
        else:
            break
    profile.close()
    time.sleep(1)
    # 发送开机指令并记录开机时间
    startCmd = bytes('sensorStart\n', encoding='ASCII')
    user_serial.write(startCmd)
    start_time = time.strftime('%Y-%m-%d_%H_%M_%S')
    print('开启时间：%s ' % start_time)
    while True:
        if data_serial.inWaiting() > 0:
            # 获取数据头
            data_head = data_serial.read(8)

            # 将byte数据转换为字符串
            data_head = data_head.hex()
            # 检测完整数据包
            if data_head == '0201040306050807':
                data_package = ''
                end_buff = ''
                while True:

                    # 检测完整数据包
                    data_recv = data_serial.read(1)
                    data_recv = data_recv.hex()
                    # print(data_recv)
                    # 数据包以'0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f'结尾
                    if data_recv == '0f':
                        end_buff = end_buff + data_recv
                        data_package = data_package + data_recv
                        if end_buff == '0f0f0f0f0f0f0f0f':
                            break

                    else:
                        # 如果不是这个结果，则end_buff清零
                        end_buff = ''
                        data_package = data_package + data_recv

                # 获得了一个完整的数据包
                # 判断是否丢包，如果没有丢包，则解析当前包,否则不做操作
                package = bytes.fromhex(data_package)
                # 信号队列出队
                signal_buff[:-1] = signal_buff[1:]
                if len(package) == 56:
                    temp = package[44:48]
                    # print(temp)
                    temp_float = struct.unpack('f', temp)
                    # 信号队列更新
                    signal_buff[-1] = temp_float[0]
                    # print(temp_float[0])
                else:

                    signal_buff[-1] = signal_buff[-2]
            else:
                print('出了一些问题')


def vital_parameters():
    global signal_buff, fs
    # 去除相位畸变
    body_move_signal = remove_bcg_distortion(signal_buff)
    # 提取bcg信号
    bcg = extract_heart_signal(
        body_move_signal, fs)
    rsp = body_move_signal - bcg
    rsp = rsp[int(30 * fs):int(60 * fs)]
    bcg = bcg[int(40 * fs):int(60 * fs)]
    # 对信号进行降采样
    # 心率与呼吸率降采样为为20Hz
    # 呼吸信号降采样
    rsp_length = int(len(rsp) / 5)
    index_rsp = np.linspace(
        0, np.floor((len(rsp) - 1) / 5) * 5,
        rsp_length, dtype=int)

    rsp_sample = rsp[index_rsp]

    # 心率降采样
    bcg_length = int(len(bcg) / 5)
    index_bcg = np.linspace(
        0, np.floor((len(bcg) - 1) / 5) * 5,
        bcg_length, dtype=int)
    bcg_sample = bcg[index_bcg]

    # 对rsp补零增加频率分辨率
    rsp_sample = np.hstack((rsp_sample, np.zeros((len(rsp_sample),))))
    # 对呼吸信号做fft变换
    rsp_fft = np.fft.fft(
        rsp_sample * np.sqrt(np.hanning(
            len(rsp_sample))))
    # 找出人类呼吸范围0.16-0.50Hz最大的频率点对应的index范围
    freq_rsp = np.linspace(
        0, len(rsp_fft) - 1, len(rsp_fft)) / len(rsp_fft) * 20
    min_rsp_index = np.min(np.argwhere(freq_rsp >= 0.16))
    max_rsp_index = np.max(np.argwhere(freq_rsp <= 0.5))
    # 计算平均呼吸率
    RF = (np.argmax(rsp_fft[min_rsp_index:max_rsp_index]) + min_rsp_index) / len(rsp_fft) * 20

    # 对bcg补零增加频率分辨率
    # 对bcg补零增加频率分辨率
    bcg_sample = np.hstack((bcg_sample, np.zeros((len(bcg_sample),))))
    # 对心率做fft
    bcg_fft = np.fft.fft(bcg_sample * np.sqrt(np.hanning(len(bcg_sample))))
    # 找出人类心率范围0.9-3Hz最大的频率点对应的index范围
    freq_bcg = np.linspace(
        0, len(rsp_fft) - 1, len(bcg_fft)) / len(bcg_fft) * 20
    min_bcg_index = np.min(np.argwhere(freq_bcg >= 0.9))
    max_bcg_index = np.max(np.argwhere(freq_bcg <= 3))
    HF = (np.argmax(bcg_fft[min_bcg_index:max_bcg_index]) + min_bcg_index) / len(bcg_fft) * 20
    return HF, RF, body_move_signal, bcg


def show_parameters():
    import datetime
    print('程序初始化中')
    start_time = datetime.datetime.now() + datetime.timedelta(seconds=10)
    while True:
        if datetime.datetime.now() >= start_time:
            break
    while True:
        HF, RF, body_move_signal, bcg = vital_parameters()
        start_time = datetime.datetime.now() + datetime.timedelta(seconds=2)
        while True:
            if datetime.datetime.now() >= start_time:
                print('心率：' + str(HF * 60) + '次/分, 呼吸率：' + str(RF * 60) + '次/分')
                break


if __name__ == '__main__':
    t1 = Thread(target=get_data, daemon=True)
    t1.start()
    t2 = Thread(target=show_parameters, daemon=True)
    t2.start()
    # get_data()
